package com.sie.zhq.module;

import android.util.Log;

import com.sie.zhq.constconfig.ConstDefine;
import com.sie.zhq.serialport.SerialPort;
import com.sie.zhq.tool.ByteTool;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidParameterException;

/**
 * @author benjaminwan
 */
public class SerialHelper {
    private SerialPort mSerialPort;
    private OutputStream mOutputStream;
    private InputStream mInputStream;
    private ReadThread mReadThread;
    private SendThread mSendThread;

    private static String sPort = ConstDefine.FINANCIAL_PORT;
    private int iBaudRate = 115200;
    private boolean _isOpen = false;
    private byte[] _bLoopData = new byte[]{0x30};
    private int iDelay = 500;

    private byte[] FifoBuffer = new byte[1024];
    private int ofst_free = 0, ofst_last = 0;


    //----------------------------------------------------
    public SerialHelper(String sPort, int iBaudRate) {
        this.sPort = sPort;
        this.iBaudRate = iBaudRate;
    }

    public SerialHelper() {

        this(sPort, 115200);
    }

    public SerialHelper(String sPort) {
        this(sPort, 115200);
    }

    public SerialHelper(String sPort, String sBaudRate) {
        this(sPort, Integer.parseInt(sBaudRate));
    }

    //----------------------------------------------------
    public void open() throws SecurityException, IOException, InvalidParameterException {
        mSerialPort = new SerialPort(new File(sPort), iBaudRate, 0);

        mOutputStream = mSerialPort.getOutputStream();
        mInputStream = mSerialPort.getInputStream();
        mReadThread = new ReadThread();
        mReadThread.start();
        _isOpen = true;
    }

    public void createRecvThread() {
        mReadThread = new ReadThread();
        mReadThread.start();
    }

    //----------------------------------------------------
    public void close() {
        if (mReadThread != null)
            mReadThread.interrupt();
        if (mSerialPort != null) {
            mSerialPort.close();
            mSerialPort = null;
        }
        _isOpen = false;
    }

    public void Push(byte[] bInArray, int length) {
        //if(length+ofst_free)
        /*
        for(int i=0;i<length;i++){
    		FifoBuffer[ofst_free++] = bInArray[i];
    		ofst_free %= 1024;
    	}*/
        if (ofst_free + length <= FifoBuffer.length) {
            System.arraycopy(bInArray, 0, FifoBuffer, ofst_free, length);
            ofst_free = ofst_free + length;
        } else {
            System.arraycopy(bInArray, 0, FifoBuffer, ofst_free, FifoBuffer.length - ofst_free);
            System.arraycopy(bInArray, FifoBuffer.length - ofst_free, FifoBuffer, 0, length - FifoBuffer.length + ofst_free);
            ofst_free = length - FifoBuffer.length + ofst_free;
        }
    }

    public int Pop(byte[] bOutArray, int timeout) {
        for (int i = 0; i < timeout; i += 100) {
            if (ofst_free != ofst_last) {
                bOutArray[0] = FifoBuffer[ofst_last++];
                //Log.d("SerialHelper", "Pop: "+ByteUtil.bytearrayToHexString(bOutArray,1));
                ofst_last %= 1024;
                return 0;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return 1;
    }


    public void Quick32Crc(byte[] bData, int length, byte[] crcOut) {
        if (mSerialPort != null) {
            mSerialPort.QuickCrc32(bData, length, crcOut);
        }
    }

    //----------------------------------------------------
    public void send(byte[] bOutArray) {
        try {
            Log.d("SerialHelper", "send:" + ByteTool.bytearrayToHexString(bOutArray, bOutArray.length));
            mOutputStream.write(bOutArray);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //----------------------------------------------------
    public void sendHex(String sHex) {
        byte[] bOutArray = ByteTool.hexStr2Bytes(sHex);
        send(bOutArray);
    }

    //----------------------------------------------------
    public void sendTxt(String sTxt) {
        byte[] bOutArray = sTxt.getBytes();
        send(bOutArray);
    }

    //----------------------------------------------------
    private class ReadThread extends Thread {
        @Override
        public void run() {
            super.run();
            while (!isInterrupted()) {
                try {

                    if (mInputStream == null) return;
                    byte[] buffer = new byte[512];
                    //Log.d("serialhelper","begin recv:");
                    int size = mInputStream.read(buffer);
                    //Log.d("serialhelper","end recv");
                    if (size > 0) {
                        //ComBean ComRecData = new ComBean(sPort,buffer,size);
                        //onDataReceived(ComRecData);
                        Push(buffer, size);
                        //Log.d("SerialHelper", "recv:" + ByteUtil.bytearrayToHexString(buffer,size));
                    }
                    /*
					try
					{
						//Thread.sleep(50);
					} catch (InterruptedException e)
					{
						e.printStackTrace();
					}*/
                } catch (Throwable e) {
                    e.printStackTrace();
                    return;
                }
            }
        }
    }

    //----------------------------------------------------
    private class SendThread extends Thread {
        public boolean suspendFlag = true;

        @Override
        public void run() {
            super.run();
            while (!isInterrupted()) {
                synchronized (this) {
                    while (suspendFlag) {
                        try {
                            wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
                send(getbLoopData());
                try {
                    Thread.sleep(iDelay);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        public void setSuspendFlag() {
            this.suspendFlag = true;
        }


        public synchronized void setResume() {
            this.suspendFlag = false;
            notify();
        }
    }

    //----------------------------------------------------
    public int getBaudRate() {
        return iBaudRate;
    }

    public boolean setBaudRate(int iBaud) {
        if (_isOpen) {
            return false;
        } else {
            iBaudRate = iBaud;
            return true;
        }
    }

    public boolean setBaudRate(String sBaud) {
        int iBaud = Integer.parseInt(sBaud);
        return setBaudRate(iBaud);
    }

    //----------------------------------------------------
    public String getPort() {
        return sPort;
    }

    public boolean setPort(String sPort) {
        if (_isOpen) {
            return false;
        } else {
            this.sPort = sPort;
            return true;
        }
    }

    //----------------------------------------------------
    public boolean isOpen() {
        return _isOpen;
    }

    //----------------------------------------------------
    public byte[] getbLoopData() {
        return _bLoopData;
    }

    //----------------------------------------------------
    public void setbLoopData(byte[] bLoopData) {
        this._bLoopData = bLoopData;
    }

    //----------------------------------------------------
    public void setTxtLoopData(String sTxt) {
        this._bLoopData = sTxt.getBytes();
    }

    //----------------------------------------------------
    public void setHexLoopData(String sHex) {
        this._bLoopData = ByteTool.hexStr2Bytes(sHex);
    }

    //----------------------------------------------------
    public int getiDelay() {
        return iDelay;
    }

    //----------------------------------------------------
    public void setiDelay(int iDelay) {
        this.iDelay = iDelay;
    }

    //----------------------------------------------------
    public void startSend() {
        if (mSendThread != null) {
            mSendThread.setResume();
        }
    }

    //----------------------------------------------------
    public void stopSend() {
        if (mSendThread != null) {
            mSendThread.setSuspendFlag();
        }
    }

    public void sendMcuCommand(String command) {
        CharSequence t = command;
        int i;

        Log.d("SerialHelper", " " + t + " , length  " + t.length());
        char[] text = new char[t.length()];

        for (i = 0; i < t.length(); i++) {
            text[i] = t.charAt(i);
        }
        try {
            mOutputStream.write(new String(text).getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //----------------------------------------------------
    //protected abstract void onDataReceived(ComBean ComRecData);
}